package cn.juque.systemservice.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.juque.common.constants.MessageEnum;
import cn.juque.common.constants.StringConstants;
import cn.juque.common.constants.TreeNodeConstants;
import cn.juque.common.exception.AppException;
import cn.juque.systemservice.domain.MenuInfoDO;
import cn.juque.systemservice.entity.MenuInfo;
import cn.juque.systemservice.mapper.MenuInfoMapper;
import cn.juque.systemservice.service.IMenuInfoService;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author JUQUE
 * @version 1.0.0
 * <ul>
 *  <li>simple-generator</li>
 *  <li>菜单</li>
 * </ul>
 * @date 2023-01-06 15:09:48
 **/
@Service("menuInfoService")
public class MenuInfoServiceImpl implements IMenuInfoService {

    @Resource
    private MenuInfoMapper menuInfoMapper;

    /**
     * 查询
     *
     * @param menuInfo menuInfo
     * @return List
     */
    @Override
    public List<MenuInfoDO> listInfoWithoutPage(MenuInfoDO menuInfo) {
        List<MenuInfoDO> list = this.menuInfoMapper.queryInfoList(menuInfo);
        this.build(list);
        return list;
    }

    /**
     * 详情
     *
     * @param id 主键
     * @return MenuInfo
     */
    @Override
    public MenuInfoDO detail(String id) {
        MenuInfo menuInfo = this.menuInfoMapper.selectById(id);
        MenuInfoDO menuInfoDO = new MenuInfoDO();
        BeanUtil.copyProperties(menuInfo, menuInfoDO);
        this.build(CollUtil.newArrayList(menuInfoDO));
        return menuInfoDO;
    }

    /**
     * 保存
     *
     * @param menuInfo menuInfo
     */
    @Override
    public void saveInfo(MenuInfo menuInfo) {
        // 计算级次码

        if (TreeNodeConstants.ROOT_CHAR.equals(menuInfo.getParentMenuId())) {
            menuInfo.setLevelCode(menuInfo.getMenuId());
        } else {
            MenuInfo parentMenu = this.menuInfoMapper.selectById(menuInfo.getParentMenuId());
            menuInfo.setLevelCode(parentMenu.getLevelCode() + StringConstants.VERTICAL_LINE + menuInfo.getMenuId());
        }
        boolean flag = SqlHelper.retBool(this.menuInfoMapper.insert(menuInfo));
        if (!flag) {
            throw new AppException(MessageEnum.SAVE_FAIL);
        }
    }

    /**
     * 更新
     *
     * @param menuInfo menuInfo
     */
    @Override
    public void updateInfo(MenuInfo menuInfo) {
        boolean flag = SqlHelper.retBool(this.menuInfoMapper.updateById(menuInfo));
        if (!flag) {
            throw new AppException(MessageEnum.UPDATE_FAIL);
        }
    }

    /**
     * 删除
     *
     * @param ids 主键列表
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteInfo(List<String> ids) {
        if (CollUtil.isEmpty(ids)) {
            return;
        }
        int count = this.menuInfoMapper.deleteBatchIds(ids);
        if (count != ids.size()) {
            throw new AppException(MessageEnum.DELETE_FAIL);
        }
    }

    private void build(List<MenuInfoDO> list) {
        if (CollUtil.isEmpty(list)) {
            return;
        }
        Set<String> parentIdList = list.stream().map(MenuInfo::getParentMenuId).collect(Collectors.toSet());
        List<MenuInfo> menuList = this.menuInfoMapper.selectBatchIds(parentIdList);
        Map<String, MenuInfo> menuMap = menuList.stream().collect(Collectors.toMap(MenuInfo::getMenuId, t -> t, (k1, k2) -> k2));
        MenuInfo root = new MenuInfo();
        root.setMenuId(TreeNodeConstants.ROOT_CHAR);
        root.setMenuName(TreeNodeConstants.ROOT_NAME);
        menuMap.put(root.getMenuId(), root);
        list.parallelStream().forEach(f -> f.setParentMenuName(menuMap.get(f.getParentMenuId()).getMenuName()));
    }
}
